package jmu.test.util.concurent ;


public class ActionThread extends Thread
{
    private static int EMPTY_LOOPS = 5 ;

    public static ActionThread getInstance ( final ActionManager source, final ActionResultObserver observer )
    {
        return getInstance ( source, observer, true ) ;
    }

    public static ActionThread getInstance ( final ActionManager source, final ActionResultObserver observer,
            boolean start )
    {
        ActionThread thread = new ActionThread ( source, observer ) ;
        if ( start )
        {
            thread.start () ;
        }

        return thread ;
    }

    // store internal objects
    private ActionResultObserver observer = null ;
    private ActionManager source ;

    private ActionThread ( final ActionManager source, final ActionResultObserver observer )
    {
        setObserver ( observer ) ;
        setSource ( source ) ;
    }

    protected ActionResultObserver getObserver ()
    {
        return observer ;
    }

    protected ActionManager getSource ()
    {
        return source ;
    }

    @Override
    public void run ()
    {
        int loop = 0 ;

        Action action = null ;
        while ( !isInterrupted () )
        {
            while ( !getSource ().isEmpty () )
            {
                synchronized ( getSource ().locker () )
                {
                    if ( !getSource ().isEmpty () )
                    {
                        action = getSource ().get () ;
                    }
                }
                if ( null != action )
                {
                    getObserver ().handle ( action.process () ) ;
                    loop = 0 ;
                }
            }

            // stop work if there is nothing to do
            if ( loop == EMPTY_LOOPS )
            {
                interrupt () ;
                continue ;
            }

            // update empty loop counter
            loop++ ;

            // do pause
            sleep () ;
        }
    }

    protected void setObserver ( final ActionResultObserver observer )
    {
        if ( null == observer )
        {
            throw new IllegalArgumentException ( "observer can't be null" ) ;
        }
        this.observer = observer ;
    }

    protected void setSource ( final ActionManager source )
    {
        if ( null == source )
        {
            throw new IllegalArgumentException ( "source can't be null" ) ;
        }
        this.source = source ;
    }

    private void sleep ()
    {
        try
        {
            sleep ( 1000 ) ;
        }
        catch ( final InterruptedException e )
        {
            // ignore
        }
    }
}
